/*
 * Copyright (c) 2010, Nikolaus Moll
 * All rights reserved.
 */
package net.miblounge.gradecalculator.gui.widgets;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import net.miblounge.gradecalculator.core.AbstractDataProvider;
import net.miblounge.gradecalculator.core.descriptors.CourseOfStudiesDescription;
import net.miblounge.gradecalculator.core.descriptors.StudyRegulationsDescription;
import net.miblounge.gradecalculator.core.descriptors.modulelistitems.SelectableModuleLists;
import net.miblounge.gradecalculator.core.descriptors.modulelists.ModuleList;
import net.miblounge.gradecalculator.core.interfaces.IModuleIdentificator;
import net.miblounge.gradecalculator.core.interfaces.IModuleListItem;
import net.miblounge.gradecalculator.core.student.Student;
import net.miblounge.gradecalculator.gui.interfaces.ISelectableModuleListsSelectionListener;
import net.miblounge.miglayout.qt.MigLayout;

import com.trolltech.qt.gui.QGroupBox;
import com.trolltech.qt.gui.QWidget;

public class SelectionsWidget extends QGroupBox implements ISelectableModuleListsSelectionListener
{
    private CourseOfStudiesDescription currentCourseOfStudies = null;
    private final MigLayout layout;
    private final Map<String, ModuleListsSelectorWidget> groups;
    private final Map<String, List<SelectableModuleLists>> dependencies;

    private final Student student;

    public SelectionsWidget(final String title, final QWidget parent, final Student student)
    {
        super(title, parent);
        this.student = student;

        groups = new HashMap<String, ModuleListsSelectorWidget>();
        dependencies = new HashMap<String, List<SelectableModuleLists>>();

        layout = new MigLayout("", "[shrink 0, 150::][grow]", "");
        setLayout(layout);

        setVisible(false);
    }

    private void clearLayout()
    {
        dependencies.clear();

        for (final ModuleListsSelectorWidget widget : groups.values()) {
            widget.remove();
        }

        groups.clear();
    }

    private ModuleList getSMLParent(final IModuleIdentificator lists)
    {
        IModuleIdentificator item = lists.getParent();
        while (item != null) {
            if (item instanceof ModuleList) {
                if (item.getParent() == null) {
                    // root list
                    return null;
                }
                return (ModuleList) item;
            }
            item = item.getParent();
        }

        return null;
    }

    private void addSLMDependency(final String parent, final SelectableModuleLists child)
    {
        final List<SelectableModuleLists> list;
        if (dependencies.containsKey(parent)) {
            list = dependencies.get(parent);
        }
        else {
            list = new LinkedList<SelectableModuleLists>();
            dependencies.put(parent, list);
        }

        list.add(child);
    }

    private boolean createGroups(final List<SelectableModuleLists> list)
    {
        clearLayout();
        if (list.size() == 0) {
            return false;
        }

        for (final SelectableModuleLists sml : list) {
            final ModuleListsSelectorWidget grp = new ModuleListsSelectorWidget(this, sml);
            grp.addSelectionListener(this);
            groups.put(sml.getIdentifier(), grp);

            final ModuleList parent = getSMLParent(sml);
            if (parent != null) {
                grp.setSelectionEnabled(false);
                addSLMDependency(parent.getIdentifier(), sml);
                // parent = getSMLParent(parent);
            }
        }

        for (final String moduleList : student.getSelectedModuleLists()) {
            final int separator = moduleList.lastIndexOf('.');
            final String parent = moduleList.substring(0, separator);
            final String name = moduleList.substring(separator + 1);

            if (!groups.containsKey(parent)) {
                continue;
            }
            final ModuleListsSelectorWidget grp = groups.get(parent);
            grp.setItemSelected(name, true);
        }

        return true;
    }

    public void apply()
    {
        final List<String> list = new ArrayList<String>();

        for (final String parent : groups.keySet()) {
            final ModuleListsSelectorWidget grp = groups.get(parent);

            for (final String name : grp.getSelectedItems()) {
                final String qualifiedName = parent + "." + name;
                list.add(qualifiedName);
            }
        }

        student.setSelectedModuleLists(list);
    }

    public void setCourseOfStudiesDescription(final CourseOfStudiesDescription description)
    {
        if (description == null) {
            if (currentCourseOfStudies == null) {
                return;
            }

            currentCourseOfStudies = null;
            clearLayout();
            setVisible(false);

            adjustParentSize();
            return;
        }

        if (description.equals(currentCourseOfStudies)) {
            return;
        }

        currentCourseOfStudies = description;

        final String descriptor = currentCourseOfStudies.toString();
        final StudyRegulationsDescription spodescription = AbstractDataProvider.getInstance().getSPODescription(
                descriptor);
        final List<SelectableModuleLists> list = getSelectableModuleLists(spodescription.getModuleList());
        setVisible(createGroups(list));

        adjustParentSize();
    }

    private void adjustParentSize()
    {
        QWidget parent = parentWidget();
        while (parent != null) {
            parent.adjustSize();

            if (parent.isWindow()) {
                return;
            }

            parent = parent.parentWidget();
        }
    }

    private static List<SelectableModuleLists> getSelectableModuleLists(final ModuleList root)
    {
        final List<SelectableModuleLists> result = new ArrayList<SelectableModuleLists>();
        for (final IModuleListItem m : root.getModules()) {
            if (!(m instanceof SelectableModuleLists)) {
                continue;
            }
            final SelectableModuleLists slm = (SelectableModuleLists) m;

            result.add(slm);
            for (final ModuleList ml : slm.getModuleLists()) {
                result.addAll(getSelectableModuleLists(ml));
            }
        }

        return result;
    }

    @Override
    public void selectionChanged(final String moduleListId, final boolean selected)
    {
        if (!dependencies.containsKey(moduleListId)) {
            return;
        }

        final List<SelectableModuleLists> dependingLists = dependencies.get(moduleListId);
        for (final SelectableModuleLists sml : dependingLists) {
            final ModuleListsSelectorWidget group = groups.get(sml.getIdentifier());

            group.setSelectionEnabled(selected);
            selectionChanged(sml.getIdentifier(), selected);
        }
        adjustParentSize();
    }
}
